"""
qt_application.py
By IT小强xqitw.cn <mail@xqitw.cn>
At 6/16/21 6:13 PM
"""
import time
from webbrowser import open
from pyperclip import copy
from json import dumps, loads
from re import search
from threading import Thread

from PySide2.QtCore import QObject, Signal, Qt, QEvent
from PySide2.QtGui import QIcon
from PySide2.QtUiTools import QUiLoader
from PySide2.QtWidgets import (
    QMenu, QAction, QSystemTrayIcon,
    QMessageBox, QTextBrowser, QInputDialog, QLineEdit,
    QTableWidgetItem, QTableWidget, QStatusBar
)

from wslm import windows_command

from .decorators import signal_emit_text_ui
from .utils import resource_path, get_ports_from_string, signal_emit_text, run_cmd, run_cmd_line, is_user_an_admin
from .setting_manage import setting_manage
from . import resource as qrc_resource


class QtCoreSignal(QObject):
    text_signal = Signal(QTextBrowser, str)
    statusbar_signal = Signal(QStatusBar, str)
    port_info_table_signal = Signal(QTableWidget, str)
    wall_info_table_signal = Signal(QTableWidget, str)
    wsl_info_table_signal = Signal(QTableWidget, str)
    default_signal = Signal(str)


qt_core_signal = QtCoreSignal()


class QSystemTray:

    def init_q_system_tray(self):

        self.tp = QSystemTrayIcon(self.ui)
        self.tp.setIcon(QIcon(':icon/logo.ico'))
        self.ui_hide = QAction(icon=QIcon(':icon/hide.png'), text='隐藏', triggered=self.ui.hide)
        self.ui_show = QAction(icon=QIcon(':icon/show.png'), text='显示', triggered=self.ui.show)
        self.ui_exit = QAction(icon=QIcon(':icon/exit.png'), text='退出', triggered=self.quit_app)
        self.tp_menu = QMenu()
        self.tp_menu.addAction(self.ui_hide)
        self.tp_menu.addAction(self.ui_show)
        self.tp_menu.addAction(self.ui_exit)
        self.tp.setContextMenu(self.tp_menu)
        self.tp.activated.connect(self.__tp_connect_action)
        self.tp.show()
        self.tp.showMessage(
            'WSL管理工具',
            '启动成功',
            QSystemTrayIcon.MessageIcon.Information
        )

    def __tp_connect_action(self, activation_reason):
        """
        监听托盘图标点击
        :param activation_reason: 点击类型
        :return:
        """
        if activation_reason == QSystemTrayIcon.ActivationReason.Trigger:
            # 左单击
            if self.ui.isHidden():
                self.show_front()
            else:
                self.ui.hide()
        elif activation_reason == QSystemTrayIcon.ActivationReason.Context:
            # 右单击
            self.tp_menu.show()
        elif activation_reason == QSystemTrayIcon.ActivationReason.DoubleClick:
            # 双击
            self.show_front()


class QSettings:

    def init_q_settings(self):
        # 设置选中状态
        self.ui.auto_start_wsl.setChecked(self.setting_manage.get('auto_start_wsl', False))
        self.ui.fire_wall_open.setChecked(self.setting_manage.get('fire_wall_open', False))
        self.ui.fire_wall_close.setChecked(self.setting_manage.get('fire_wall_close', False))
        self.ui.start_show_ui.setChecked(self.setting_manage.get('start_show_ui', False))

        # 保存配置按钮监听
        self.ui.save_settings.clicked.connect(self.__save_settings)

        self.ui.action_save_settings.setIcon(QIcon(':icon/save.png'))
        self.ui.action_save_settings.triggered.connect(self.__save_settings)

        # 隐藏工具栏
        self.ui.action_hide_tool_bar.setIcon(QIcon(':icon/hide.png'))
        self.ui.action_hide_tool_bar.triggered.connect(self.ui.tool_bar.hide)

        # 显示工具栏
        self.ui.action_show_tool_bar.setIcon(QIcon(':icon/show.png'))
        self.ui.action_show_tool_bar.triggered.connect(self.ui.tool_bar.show)

        # 设置脚本内容
        self.ui.bat_text.appendPlainText(self.setting_manage.get('wsl_bat_content', ''))
        self.ui.port_text.appendPlainText(self.setting_manage.get('wsl_port_text', ''))

    def __save_settings(self):
        """
        保存全部配置
        :return:
        """
        # 保存配置信息
        self.setting_manage.set('fire_wall_open', self.ui.fire_wall_open.isChecked())
        self.setting_manage.set('fire_wall_close', self.ui.fire_wall_close.isChecked())
        self.setting_manage.set('auto_start_wsl', self.ui.auto_start_wsl.isChecked())
        self.setting_manage.set('start_show_ui', self.ui.start_show_ui.isChecked())
        self.setting_manage.set('wsl_bat_content', self.ui.bat_text.toPlainText())
        self.setting_manage.set('wsl_port_text', self.ui.port_text.toPlainText())

        # 保存成功提示
        QMessageBox.information(self.ui, '系统提示', '配置保存成功!')


class QtApplication(QSystemTray, QSettings, QObject):
    """
    QtApplication
    """

    wsl_ip = None

    def __init__(self, qt_application=None):
        super().__init__()
        self.qt_application = qt_application
        self.setting_manage = setting_manage

        # 加载UI文件
        self.ui = QUiLoader().load(resource_path('resource', 'wslm.ui'))

        self.ui.setWindowTitle(self.ui.windowTitle() + ('（管理员）' if is_user_an_admin() else '（请以管理员身份运行）'))

        # 设置界面图标
        app_icon = QIcon(':icon/logo.ico')
        self.ui.setWindowIcon(app_icon)

        # 初始化系统托盘
        self.init_q_system_tray()

        # 初始化配置项
        self.init_q_settings()

        # 注册事件监听
        self.ui.installEventFilter(self)

        # 获取子系统IP
        self.wsl_ip = self.__get_wsl_ip()

        # 文本框信号
        qt_core_signal.text_signal.connect(self.insert_plain_text)
        # 端口信息表格信号
        qt_core_signal.port_info_table_signal.connect(self.set_port_info_table_items)
        # 防火墙信息表格信号
        qt_core_signal.wall_info_table_signal.connect(self.set_wall_info_table_items)
        # 子系统信息表格信号
        qt_core_signal.wsl_info_table_signal.connect(self.set_wsl_info_table_items)
        # 状态栏显示信息
        qt_core_signal.statusbar_signal.connect(self.show_message_statusbar)

        # 添加端口
        self.ui.action_add_port.setIcon(QIcon(':icon/add.png'))
        self.ui.action_add_port.triggered.connect(self.__add_port)
        # 删除端口
        self.ui.action_del_port.setIcon(QIcon(':icon/del.png'))
        self.ui.action_del_port.triggered.connect(self.__del_port)
        # 重置端口
        self.ui.action_reset_port.setIcon(QIcon(':icon/reset.png'))
        self.ui.action_reset_port.triggered.connect(self.__reset_port)
        # 更新端口
        self.ui.action_update_port.setIcon(QIcon(':icon/update.png'))
        self.ui.action_update_port.triggered.connect(self.__update_port)

        # 添加防火墙
        self.ui.action_add_wall.setIcon(QIcon(':icon/add.png'))
        self.ui.action_add_wall.triggered.connect(self.__add_wall)
        # 删除防火墙
        self.ui.action_del_wall.setIcon(QIcon(':icon/del.png'))
        self.ui.action_del_wall.triggered.connect(self.__del_wall)
        # 清除全部防火墙
        self.ui.action_reset_wall.setIcon(QIcon(':icon/reset.png'))
        self.ui.action_reset_wall.triggered.connect(self.__reset_wall)

        # 终止所有子系统
        self.ui.action_shutdown_wsl.setIcon(QIcon(':icon/stop.png'))
        self.ui.action_shutdown_wsl.triggered.connect(self.__shutdown_wsl)
        # 执行默认启动脚本
        self.ui.action_start_wsl.setIcon(QIcon(':icon/start.png'))
        self.ui.action_start_wsl.triggered.connect(self.__start_wsl)
        # 更新子系统IP
        self.ui.action_get_wsl_ip.setIcon(QIcon(':icon/ip.png'))
        self.ui.action_get_wsl_ip.triggered.connect(self.__get_wsl_ip_force)
        self.ui.btn_get_wsl_ip.clicked.connect(self.__get_wsl_ip_force)

        # 表格设置
        self.ui.port_info_table.horizontalHeader().setStretchLastSection(True)
        self.ui.wall_info_table.horizontalHeader().setStretchLastSection(True)
        self.ui.wsl_info_table.horizontalHeader().setStretchLastSection(True)

        # 端口信息表格单击
        self.ui.port_info_table.clicked.connect(self.__port_info_table_click)
        # 防火墙信息表格单击
        self.ui.wall_info_table.clicked.connect(self.__wall_info_table_click)

        # 复制ip
        self.ui.btn_copy_wsl_ip.clicked.connect(self.__copy_wsl_ip)

        # 转发配置保存的端口
        self.ui.btn_update_ports.clicked.connect(self.__btn_update_ports)

        # 跳转项目地址
        self.ui.action_open_gitee_url.setIcon(QIcon(':icon/gitee.png'))
        self.ui.action_open_gitee_url.triggered.connect(self.__open_gitee_url)

        # 获取子系统信息，初始化表格
        self.__get_wsl_info()
        # 获取端口信息，初始化表格
        self.__get_port_info()
        # 获取防火墙信息，初始化表格
        self.__get_wall_info()

    def eventFilter(self, obj, event) -> bool:
        if obj is self.ui and event.type() == QEvent.Close:
            self.quit_app()
            event.ignore()
            return True
        return super().eventFilter(obj, event)

    @staticmethod
    def __open_gitee_url():
        url = 'https://gitee.com/itxq/wslm-gui'
        open(url)

    def __copy_wsl_ip(self):
        copy(self.ui.line_edit_wsl_ip.text())
        QMessageBox.information(self.ui, '系统提示', '已成功复制!')

    def __port_info_table_click(self, q_model_index, *args, **kwargs):
        port = self.ui.port_info_table.item(q_model_index.row(), 0).text()
        choice = QMessageBox.question(
            self.ui,
            '删除确认',
            f'确定要删除端口：{port}吗？')

        if choice == QMessageBox.Yes:
            thread_port = Thread(target=self.__del_port_thread, kwargs={"port": port})
            thread_port.start()
            if self.setting_manage.get('fire_wall_close', False):
                thread_wall = Thread(target=self.__del_wall_thread, kwargs={"port": port})
                thread_wall.start()

    def __wall_info_table_click(self, q_model_index, *args, **kwargs):
        port = self.ui.wall_info_table.item(q_model_index.row(), 0).text()
        wall_type = self.ui.wall_info_table.item(q_model_index.row(), 1).text()

        choice = QMessageBox.question(
            self.ui,
            '删除确认',
            f'确定要删除防火墙：{port}-{wall_type}吗？')

        if choice == QMessageBox.Yes:
            thread_wall = Thread(target=self.__del_wall_thread, kwargs={"port": port, "wall_type": wall_type})
            thread_wall.start()

    def __btn_update_ports(self):
        ports = self.setting_manage.get('wsl_port_text', '')
        self.__update_port(ports=ports)

    def __update_port(self, **kwargs):
        ports = kwargs.get('ports', None)
        thread_port = Thread(target=self.__update_port_thread, kwargs={"ports": ports})
        thread_port.start()

    @signal_emit_text_ui(qt_core_signal.statusbar_signal, 'statusbar', '更新端口转发成功.', is_end=True)
    @signal_emit_text_ui(qt_core_signal.statusbar_signal, 'statusbar', f'正在更新端口转发...')
    def __update_port_thread(self, ports=None):
        if ports is None:
            port_info_dict = self.__get_port_info_thread()
            ports = [i.get('listen_port', '') for i in port_info_dict]
        self.__add_port_thread(port=ports)
        if self.setting_manage.get('fire_wall_open', False):
            self.__add_wall_thread(port=ports)

    def __reset_port(self):
        choice = QMessageBox.question(
            self.ui,
            '清除确认',
            f'确定要清除全部端口转发吗？')

        if choice == QMessageBox.Yes:
            thread_port = Thread(target=self.__reset_port_thread)
            thread_port.start()
            if self.setting_manage.get('fire_wall_close', False):
                thread_wall = Thread(target=self.__reset_wall_thread)
                thread_wall.start()

    @signal_emit_text_ui(qt_core_signal.statusbar_signal, 'statusbar', '清除端口转发成功.', is_end=True)
    @signal_emit_text_ui(qt_core_signal.statusbar_signal, 'statusbar', f'正在清除端口转发...')
    def __reset_port_thread(self):
        command = self.get_windows_command_port().get_cmd_port_reset()
        run_cmd(command=command, encoding=self.get_encoding())
        self.__get_port_info_thread()

    def __add_port(self):
        _port, _ = QInputDialog.getText(
            self.ui,
            "添加端口转发",
            "请输入要转发的端口号:",
            QLineEdit.Normal,
            ""
        )

        if _:
            thread_port = Thread(target=self.__add_port_thread, kwargs={"port": _port})
            thread_port.start()
            if self.setting_manage.get('fire_wall_open', False):
                thread_wall = Thread(target=self.__add_wall_thread, kwargs={"port": _port})
                thread_wall.start()

    def __add_port_thread(self, port):
        wsl_ip = self.__get_wsl_ip(force=True)
        ports = get_ports_from_string(port_string=port)
        for port in ports:
            signal_emit_text(qt_core_signal.statusbar_signal, self.ui.statusbar, f'正在转发端口:{port}...')
            command = self.get_windows_command_port().get_cmd_port_add(port=port, ip=wsl_ip)
            run_cmd(command=command, encoding=self.get_encoding())
        self.__get_port_info_thread()

    def __del_port(self):
        _port, _ = QInputDialog.getText(
            self.ui,
            "删除端口转发",
            "请输入要删除的端口号:",
            QLineEdit.Normal,
            ""
        )

        if _:
            thread_port = Thread(target=self.__del_port_thread, kwargs={"port": _port})
            thread_port.start()
            if self.setting_manage.get('fire_wall_close', False):
                thread_wall = Thread(target=self.__del_wall_thread, kwargs={"port": _port})
                thread_wall.start()

    def __del_port_thread(self, port):
        ports = get_ports_from_string(port_string=port)
        for port in ports:
            signal_emit_text(qt_core_signal.statusbar_signal, self.ui.statusbar, f'正在删除端口:{port}...')
            command = self.get_windows_command_port().get_cmd_port_del(port=port)
            run_cmd(command=command, encoding=self.get_encoding())
        self.__get_port_info_thread()

    def __get_port_info(self):
        """
        获取端口转发信息
        :return:
        """
        thread = Thread(target=self.__get_port_info_thread)
        thread.start()

    @signal_emit_text_ui(qt_core_signal.statusbar_signal, 'statusbar', '端口转发信息获取成功.', is_end=True)
    @signal_emit_text_ui(qt_core_signal.statusbar_signal, 'statusbar', '正在获取端口转发信息...')
    def __get_port_info_thread(self):
        cmd_port_obj = self.get_windows_command_port()
        cmd_result = run_cmd(command=cmd_port_obj.get_cmd_port_info(), encoding=self.get_encoding()).splitlines()
        port_info_dict = cmd_port_obj.port_info_to_list(cmd_result)
        port_info = dumps(port_info_dict, ensure_ascii=False)
        signal_emit_text(qt_core_signal.port_info_table_signal, self.ui.port_info_table, port_info)
        return port_info_dict

    def __reset_wall(self):
        choice = QMessageBox.question(
            self.ui,
            '清除确认',
            f'确定要清除防火墙吗？')

        if choice == QMessageBox.Yes:
            thread = Thread(target=self.__reset_wall_thread)
            thread.start()

    @signal_emit_text_ui(qt_core_signal.statusbar_signal, 'statusbar', '清除防火墙成功.', is_end=True)
    @signal_emit_text_ui(qt_core_signal.statusbar_signal, 'statusbar', f'正在清除防火墙...')
    def __reset_wall_thread(self):
        command = self.get_windows_command_wall().get_cmd_wall_reset()
        run_cmd(command=command, encoding=self.get_encoding())
        self.__get_wall_info_thread()

    def __add_wall(self):
        _port, _ = QInputDialog.getText(
            self.ui,
            "添加防火墙",
            "请输入要转发的端口号:",
            QLineEdit.Normal,
            ""
        )

        if _:
            thread = Thread(target=self.__add_wall_thread, kwargs={"port": _port})
            thread.start()

    def __add_wall_thread(self, port, wall_type=None):
        ports = get_ports_from_string(port_string=port)
        wall_cmd_obj = self.get_windows_command_wall()
        for port in ports:
            if not wall_type:
                self.__del_wall_one(wall_cmd_obj=wall_cmd_obj, port=port, wall_type=wall_cmd_obj.FIRE_WALL_RULE_OUT)
                self.__add_wall_one(wall_cmd_obj=wall_cmd_obj, port=port, wall_type=wall_cmd_obj.FIRE_WALL_RULE_OUT)
                self.__del_wall_one(wall_cmd_obj=wall_cmd_obj, port=port, wall_type=wall_cmd_obj.FIRE_WALL_RULE_IN)
                self.__add_wall_one(wall_cmd_obj=wall_cmd_obj, port=port, wall_type=wall_cmd_obj.FIRE_WALL_RULE_IN)
            else:
                self.__del_wall_one(wall_cmd_obj=wall_cmd_obj, port=port, wall_type=wall_type)
                self.__add_wall_one(wall_cmd_obj=wall_cmd_obj, port=port, wall_type=wall_type)
        self.__get_wall_info_thread()

    def __add_wall_one(self, wall_cmd_obj, port, wall_type):
        signal_emit_text(
            qt_core_signal.statusbar_signal,
            self.ui.statusbar,
            f'正在添加防火墙:{port}-{wall_type}...'
        )
        command = wall_cmd_obj.get_cmd_wall_add(port=port, wall_type=wall_type)
        run_cmd(command=command, encoding=self.get_encoding())

    def __del_wall(self):
        _port, _ = QInputDialog.getText(
            self.ui,
            "删除防火墙",
            "请输入要删除的端口号:",
            QLineEdit.Normal,
            ""
        )

        if _:
            thread = Thread(target=self.__del_wall_thread, kwargs={"port": _port})
            thread.start()

    def __del_wall_thread(self, port, wall_type=None):
        ports = get_ports_from_string(port_string=port)
        wall_cmd_obj = self.get_windows_command_wall()
        for port in ports:
            if not wall_type:
                self.__del_wall_one(wall_cmd_obj=wall_cmd_obj, port=port, wall_type=wall_cmd_obj.FIRE_WALL_RULE_OUT)
                self.__del_wall_one(wall_cmd_obj=wall_cmd_obj, port=port, wall_type=wall_cmd_obj.FIRE_WALL_RULE_IN)
            else:
                self.__del_wall_one(wall_cmd_obj=wall_cmd_obj, port=port, wall_type=wall_type)
        self.__get_wall_info_thread()

    def __del_wall_one(self, wall_cmd_obj, port, wall_type):
        signal_emit_text(
            qt_core_signal.statusbar_signal,
            self.ui.statusbar,
            f'正在删除防火墙:{port}-{wall_type}...'
        )
        command = wall_cmd_obj.get_cmd_wall_del(port=port, wall_type=wall_type)
        run_cmd(command=command, encoding=self.get_encoding())

    def __get_wall_info(self):
        """
        获取防火墙信息
        :return:
        """
        thread = Thread(target=self.__get_wall_info_thread)
        thread.start()

    @signal_emit_text_ui(qt_core_signal.statusbar_signal, 'statusbar', '防火墙信息获取成功.', is_end=True)
    @signal_emit_text_ui(qt_core_signal.statusbar_signal, 'statusbar', '正在获取防火墙信息...')
    def __get_wall_info_thread(self):
        cmd_wall_obj = self.get_windows_command_wall()
        cmd_result = run_cmd(command=cmd_wall_obj.get_cmd_wall_info(), encoding=self.get_encoding()).splitlines()
        wall_info = dumps(cmd_wall_obj.wall_info_to_list(cmd_result), ensure_ascii=False)
        signal_emit_text(qt_core_signal.wall_info_table_signal, self.ui.wall_info_table, wall_info)

    def __get_wsl_ip_force(self):
        return self.__get_wsl_ip(force=True)

    def __get_wsl_ip(self, **kwargs):
        """
        获取子系统IP
        :param force: 是否强制更新
        :return:
        """
        force = kwargs.get('force', False)
        if (not self.wsl_ip) or force:
            cmd_linux_obj = self.get_windows_command_linux()
            wsl_ip_result = run_cmd(command=cmd_linux_obj.get_wsl_ip(run=False), encoding=self.get_encoding())
            wsl_ip = search(cmd_linux_obj.IPV4_PATTERN, wsl_ip_result).group(0)
        else:
            wsl_ip = self.wsl_ip
        self.wsl_ip = wsl_ip
        self.ui.line_edit_wsl_ip.setText(f'{self.wsl_ip}')
        signal_emit_text(qt_core_signal.statusbar_signal, self.ui.statusbar, f'当前子系统IP：{self.wsl_ip}')
        return wsl_ip

    def __shutdown_wsl(self):
        choice = QMessageBox.question(
            self.ui,
            '终止确认',
            f'立即终止所有正在运行的分发和 WSL 2 轻型工具虚拟机？')

        if choice == QMessageBox.Yes:
            thread = Thread(target=self.__shutdown_wsl_thread)
            thread.start()

    @signal_emit_text_ui(qt_core_signal.statusbar_signal, 'statusbar', '已终止所有正在运行的分发和 WSL 2 轻型工具虚拟机.', is_end=True)
    @signal_emit_text_ui(qt_core_signal.statusbar_signal, 'statusbar', '正在终止所有正在运行的分发和 WSL 2 轻型工具虚拟机...')
    def __shutdown_wsl_thread(self):
        command = self.get_windows_command_linux().shutdown_wsl(run=False)
        run_cmd(command=command, encoding=self.get_encoding())
        self.__get_wsl_info_thread()
        signal_emit_text(qt_core_signal.statusbar_signal, self.ui.statusbar, '子系统已全部终止.')

    def __get_wsl_info(self):
        """
        获取子系统信息
        :return:
        """
        thread = Thread(target=self.__get_wsl_info_thread)
        thread.start()

    @signal_emit_text_ui(qt_core_signal.statusbar_signal, 'statusbar', '子系统信息获取成功.', is_end=True)
    @signal_emit_text_ui(qt_core_signal.statusbar_signal, 'statusbar', '正在获取子系统信息...')
    def __get_wsl_info_thread(self):
        cmd_wsl_obj = self.get_windows_command_linux()
        cmd_result = run_cmd(command=cmd_wsl_obj.get_cmd_wsl_info(), encoding=self.get_encoding()).splitlines()
        wsl_info = dumps(cmd_wsl_obj.wsl_info_to_list(cmd_result), ensure_ascii=False)
        signal_emit_text(qt_core_signal.wsl_info_table_signal, self.ui.wsl_info_table, wsl_info)

    def get_windows_command_port(self):
        return windows_command.WindowsCommandPort(**self.get_windows_command_settings())

    def get_windows_command_wall(self):
        return windows_command.WindowsCommandFireWall(**self.get_windows_command_settings())

    def get_windows_command_linux(self):
        return windows_command.WindowsCommandLinux(**self.get_windows_command_settings())

    def get_windows_command_settings(self):
        return {
            "encoding": self.get_encoding(),
            'power_shell': self.setting_manage.get(
                'windows_command_power_shell',
                windows_command.WindowsCommandBase.POWER_SHELL
            ),
            'bash_exe': self.setting_manage.get(
                'windows_command_bash_exe',
                windows_command.WindowsCommandBase.BASH_EXE
            ),
        }

    def get_encoding(self):
        return self.setting_manage.get(
            'windows_command_encoding',
            windows_command.WindowsCommandBase.CMD_ENCODING
        )

    def set_port_info_table_items(self, fb, text):
        # self.ui.tab_widget.setCurrentIndex(0)
        fb.setRowCount(0)
        port_info_list = loads(text)
        for i, port_info in enumerate(port_info_list):
            fb.insertRow(i)
            fb.setItem(i, 0, QTableWidgetItem(str(port_info.get('listen_port', ''))))
            fb.setItem(i, 1, QTableWidgetItem(str(port_info.get('listen_address', ''))))
            fb.setItem(i, 2, QTableWidgetItem(str(port_info.get('connect_port', ''))))
            fb.setItem(i, 3, QTableWidgetItem(str(port_info.get('connect_address', ''))))

    def set_wall_info_table_items(self, fb, text):
        # self.ui.tab_widget.setCurrentIndex(0)
        fb.setRowCount(0)
        wall_info_list = loads(text)
        for i, port_info in enumerate(wall_info_list):
            display_name = str(port_info.get('DisplayName', ''))
            direction = str(port_info.get('Direction', ''))
            fb.insertRow(i)
            fb.setItem(i, 0, QTableWidgetItem(display_name.split()[-1]))
            fb.setItem(i, 1, QTableWidgetItem(direction))
            fb.setItem(i, 2, QTableWidgetItem(str(port_info.get('Enabled', ''))))
            fb.setItem(i, 3, QTableWidgetItem(str(port_info.get('Action', ''))))
            fb.setItem(i, 4, QTableWidgetItem(display_name))

    def set_wsl_info_table_items(self, fb, text):
        # self.ui.tab_widget.setCurrentIndex(1)
        fb.setRowCount(0)
        wsl_info_list = loads(text)
        for i, wsl_info in enumerate(wsl_info_list):
            fb.insertRow(i)
            fb.setItem(i, 0, QTableWidgetItem(str(wsl_info.get('name', ''))))
            fb.setItem(i, 1, QTableWidgetItem(str(wsl_info.get('state', ''))))
            fb.setItem(i, 2, QTableWidgetItem(str(wsl_info.get('version', ''))))
            fb.setItem(i, 3, QTableWidgetItem(str(wsl_info.get('is_default', ''))))

    @staticmethod
    def insert_plain_text(fb, text):
        fb.append(str(text))
        fb.ensureCursorVisible()

    @staticmethod
    def show_message_statusbar(fb, text):
        cur_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        fb.showMessage(f'[{cur_time}] {text}')

    def __start_wsl(self):
        thread = Thread(target=self.__start_wsl_thread)
        thread.start()

    @signal_emit_text_ui(qt_core_signal.statusbar_signal, 'statusbar', '启动命令执行成功.', is_end=True)
    @signal_emit_text_ui(qt_core_signal.statusbar_signal, 'statusbar', '正在执行启动命令...')
    def __start_wsl_thread(self):
        wscript_exe = r'wscript.exe'
        command = f'{wscript_exe} {self.setting_manage.wsl_vbs_path} wsl'
        for i in run_cmd_line(command=command, encoding=self.get_encoding()):
            signal_emit_text(qt_core_signal.statusbar_signal, self.ui.statusbar, i)
        self.__get_wsl_ip_force()

    def quit_app(self):
        """
        退出APP
        :return:
        """
        result = QMessageBox.question(
            self.ui,
            "提示",
            "退出系统",
            QMessageBox.Yes | QMessageBox.No,
            QMessageBox.No
        )
        if result == QMessageBox.Yes:
            # 关闭窗体程序
            self.qt_application.quit()
            # 在应用程序全部关闭后，TrayIcon其实还不会自动消失，
            # 直到你的鼠标移动到上面去后，才会消失，
            # 这是个问题，（如同你terminate一些带TrayIcon的应用程序时出现的状况），
            # 这种问题的解决我是通过在程序退出前将其setVisible(False)来完成的。
            self.tp.setVisible(False)

    def show_front(self):
        flags = self.ui.windowFlags()
        self.ui.setWindowFlags(flags | Qt.WindowStaysOnTopHint)
        self.ui.show()
        self.ui.setWindowFlags(flags)
        self.ui.show()

    def auto_show(self):
        if self.setting_manage.get('auto_start_wsl', False):
            _port = self.setting_manage.get('wsl_port_text', '')
            thread_port = Thread(target=self.__add_port_thread, kwargs={"port": _port})
            thread_port.start()
            if self.setting_manage.get('fire_wall_open', False):
                thread_wall = Thread(target=self.__add_wall_thread, kwargs={"port": _port})
                thread_wall.start()
            self.__start_wsl_thread()
        if self.setting_manage.get('start_show_ui', False):
            self.show_front()
